home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / graphics / tiff / tools / tiffcmp.c < prev    next >
C/C++ Source or Header  |  1992-02-21  |  13KB  |  482 lines

  1. #ifndef lint
  2. static char rcsid[] = "$Header: /usr/people/sam/tiff/tools/RCS/tiffcmp.c,v 1.15 92/02/21 16:02:34 sam Exp $";
  3. #endif
  4.  
  5. /*
  6.  * Copyright (c) 1988, 1989, 1990, 1991, 1992 Sam Leffler
  7.  * Copyright (c) 1991, 1992 Silicon Graphics, Inc.
  8.  *
  9.  * Permission to use, copy, modify, distribute, and sell this software and 
  10.  * its documentation for any purpose is hereby granted without fee, provided
  11.  * that (i) the above copyright notices and this permission notice appear in
  12.  * all copies of the software and related documentation, and (ii) the names of
  13.  * Sam Leffler and Silicon Graphics may not be used in any advertising or
  14.  * publicity relating to the software without the specific, prior written
  15.  * permission of Sam Leffler and Silicon Graphics.
  16.  * 
  17.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
  18.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
  19.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
  20.  * 
  21.  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
  22.  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
  23.  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
  24.  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
  25.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
  26.  * OF THIS SOFTWARE.
  27.  */
  28.  
  29. #include <stdio.h>
  30. #include "tiffio.h"
  31.  
  32. #if defined(SYSV) || defined(THINK_C) || defined(applec) || defined(VMS)
  33. #define    bcmp(src, dst, len)    memcmp(dst, src, len)
  34. #endif
  35.  
  36. typedef    unsigned char u_char;
  37. typedef    unsigned short u_short;
  38. typedef    unsigned long u_long;
  39.  
  40. static    int stoponfirstdiff = 1;
  41. static    int stoponfirsttag = 1;
  42. static    u_short bitspersample = 1;
  43. static    u_short samplesperpixel = 1;
  44. static    u_long imagewidth;
  45. static    u_long imagelength;
  46.  
  47. static    int tiffcmp();
  48. static    int cmptags();
  49. static    void ContigCompare();
  50. static    void PrintDiff();
  51. static    void SeparateCompare();
  52. static    void eof();
  53.  
  54. static void
  55. usage()
  56. {
  57.     fprintf(stderr, "Usage: tiffcmp [-l] [-t] file1 file2\n");
  58.     exit(-3);
  59. }
  60.  
  61. main(argc, argv)
  62.     char *argv[];
  63. {
  64.     TIFF *tif1, *tif2;
  65.     int c, dirnum;
  66.     extern int optind;
  67.  
  68.     while ((c = getopt(argc, argv, "lt")) != -1)
  69.         switch (c) {
  70.         case 'l':
  71.             stoponfirstdiff = 0;
  72.             break;
  73.         case 't':
  74.             stoponfirsttag = 0;
  75.             break;
  76.         case '?':
  77.             usage();
  78.             /*NOTREACHED*/
  79.         }
  80.     if (argc - optind < 2)
  81.         usage();
  82.     tif1 = TIFFOpen(argv[optind], "r");
  83.     if (tif1 == NULL)
  84.         exit(-1);
  85.     tif2 = TIFFOpen(argv[optind+1], "r");
  86.     if (tif2 == NULL)
  87.         exit(-2);
  88.     dirnum = 0;
  89.     while (tiffcmp(tif1, tif2)) {
  90.         if (!TIFFReadDirectory(tif1)) {
  91.             if (!TIFFReadDirectory(tif2))
  92.                 break;
  93.             printf("No more directories for %s\n",
  94.                 TIFFFileName(tif1));
  95.             exit(1);
  96.         } else if (!TIFFReadDirectory(tif2)) {
  97.             printf("No more directories for %s\n",
  98.                 TIFFFileName(tif2));
  99.             exit(1);
  100.         }
  101.         printf("Directory %d:\n", ++dirnum);
  102.     }
  103.     exit(0);
  104. }
  105.  
  106. #ifdef EOF
  107. #undef EOF
  108. #endif
  109. #define    EOF(tif, row, sample) { \
  110.     eof(TIFFFileName(tif), row, sample); \
  111.     goto bad; \
  112. }
  113.  
  114. static    int CheckShortTag();
  115. static    int CheckLongTag();
  116.  
  117. static int
  118. tiffcmp(tif1, tif2)
  119.     TIFF *tif1, *tif2;
  120. {
  121.     u_short config1, config2;
  122.     int s, size1, size2;
  123.     u_long row;
  124.     register u_char *p1, *p2;
  125.     u_char *buf1, *buf2;
  126.  
  127.     if (!CheckShortTag(tif1, tif2, TIFFTAG_BITSPERSAMPLE, "BitsPerSample"))
  128.         return (0);
  129.     if (!CheckShortTag(tif1, tif2, TIFFTAG_SAMPLESPERPIXEL, "SamplesPerPixel"))
  130.         return (0);
  131.     if (!CheckLongTag(tif1, tif2, TIFFTAG_IMAGEWIDTH, "ImageWidth"))
  132.         return (0);
  133.     if (!cmptags(tif1, tif2))
  134.         return (1);
  135.     (void) TIFFGetField(tif1, TIFFTAG_BITSPERSAMPLE, &bitspersample);
  136.     (void) TIFFGetField(tif1, TIFFTAG_SAMPLESPERPIXEL, &samplesperpixel);
  137.     (void) TIFFGetField(tif1, TIFFTAG_IMAGEWIDTH, &imagewidth);
  138.     (void) TIFFGetField(tif1, TIFFTAG_IMAGELENGTH, &imagelength);
  139.     (void) TIFFGetField(tif1, TIFFTAG_PLANARCONFIG, &config1);
  140.     (void) TIFFGetField(tif2, TIFFTAG_PLANARCONFIG, &config2);
  141.     buf1 = (u_char *)malloc(size1 = TIFFScanlineSize(tif1));
  142.     buf2 = (u_char *)malloc(size2 = TIFFScanlineSize(tif2));
  143.     if (buf1 == NULL || buf2 == NULL) {
  144.         fprintf(stderr, "No space for scanline buffers\n");
  145.         exit(-1);
  146.     }
  147.     if (config1 != config2 && bitspersample != 8 && samplesperpixel > 1) {
  148.         fprintf(stderr,
  149. "Can't handle different planar configuration w/ different bits/sample\n");
  150.         goto bad;
  151.     }
  152. #define    pack(a,b)    ((a)<<8)|(b)
  153.     switch (pack(config1, config2)) {
  154.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_CONTIG):
  155.         for (row = 0; row < imagelength; row++) {
  156.             if (TIFFReadScanline(tif2, buf2, row, 0) < 0)
  157.                 EOF(tif2, row, -1)
  158.             for (s = 0; s < samplesperpixel; s++) {
  159.                 if (TIFFReadScanline(tif1, buf1, row, s) < 0)
  160.                     EOF(tif1, row, s)
  161.                 SeparateCompare(1, s, row, buf2, buf1);
  162.             }
  163.         }
  164.         break;
  165.     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_SEPARATE):
  166.         for (row = 0; row < imagelength; row++) {
  167.             if (TIFFReadScanline(tif1, buf1, row, 0) < 0)
  168.                 EOF(tif1, row, -1)
  169.             for (s = 0; s < samplesperpixel; s++) {
  170.                 if (TIFFReadScanline(tif2, buf2, row, s) < 0)
  171.                     EOF(tif2, row, s)
  172.                 SeparateCompare(0, s, row, buf1, buf2);
  173.             }
  174.         }
  175.         break;
  176.     case pack(PLANARCONFIG_SEPARATE, PLANARCONFIG_SEPARATE):
  177.         for (s = 0; s < samplesperpixel; s++)
  178.             for (row = 0; row < imagelength; row++) {
  179.                 if (TIFFReadScanline(tif1, buf1, row, s) < 0)
  180.                     EOF(tif1, row, s)
  181.                 if (TIFFReadScanline(tif2, buf2, row, s) < 0)
  182.                     EOF(tif2, row, s)
  183.                 ContigCompare(s, row, buf1, buf2, size1);
  184.             }
  185.         break;
  186.     case pack(PLANARCONFIG_CONTIG, PLANARCONFIG_CONTIG):
  187.         for (row = 0; row < imagelength; row++) {
  188.             if (TIFFReadScanline(tif1, buf1, row, 0) < 0)
  189.                 EOF(tif1, row, -1)
  190.             if (TIFFReadScanline(tif2, buf2, row, 0) < 0)
  191.                 EOF(tif2, row, -1)
  192.             ContigCompare(-1, row, buf1, buf2, size1);
  193.         }
  194.         break;
  195.     }
  196. done:
  197.     if (buf1) free(buf1);
  198.     if (buf2) free(buf2);
  199.     return (1);
  200. bad:
  201.     if (stoponfirstdiff)
  202.         exit(1);
  203.     if (buf1) free(buf1);
  204.     if (buf2) free(buf2);
  205.     return (0);
  206. }
  207.  
  208. #define    CmpShortField(tag, name) \
  209.     if (!CheckShortTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
  210. #define    CmpShortField2(tag, name) \
  211.     if (!CheckShort2Tag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
  212. #define    CmpLongField(tag, name) \
  213.     if (!CheckLongTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
  214. #define    CmpFloatField(tag, name) \
  215.     if (!CheckFloatTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
  216. #define    CmpStringField(tag, name) \
  217.     if (!CheckStringTag(tif1, tif2, tag, name) && stoponfirsttag) return (0)
  218.  
  219. static    int CheckShort2Tag();
  220. static    int CheckLongTag();
  221. static    int CheckFloatTag();
  222. static    int CheckStringTag();
  223.  
  224. static int
  225. cmptags(tif1, tif2)
  226.     TIFF *tif1, *tif2;
  227. {
  228.     CmpLongField(TIFFTAG_SUBFILETYPE,    "SubFileType");
  229.     CmpLongField(TIFFTAG_IMAGEWIDTH,    "ImageWidth");
  230.     CmpLongField(TIFFTAG_IMAGELENGTH,    "ImageLength");
  231.     CmpShortField(TIFFTAG_BITSPERSAMPLE,    "BitsPerSample");
  232.     CmpShortField(TIFFTAG_COMPRESSION,    "Compression");
  233.     CmpShortField(TIFFTAG_PREDICTOR,    "Predictor");
  234.     CmpShortField(TIFFTAG_PHOTOMETRIC,    "PhotometricInterpretation");
  235.     CmpShortField(TIFFTAG_THRESHHOLDING,    "Thresholding");
  236.     CmpShortField(TIFFTAG_FILLORDER,    "FillOrder");
  237.     CmpShortField(TIFFTAG_ORIENTATION,    "Orientation");
  238.     CmpShortField(TIFFTAG_SAMPLESPERPIXEL,    "SamplesPerPixel");
  239.     CmpShortField(TIFFTAG_MINSAMPLEVALUE,    "MinSampleValue");
  240.     CmpShortField(TIFFTAG_MAXSAMPLEVALUE,    "MaxSampleValue");
  241.     CmpFloatField(TIFFTAG_XRESOLUTION,    "XResolution");
  242.     CmpFloatField(TIFFTAG_YRESOLUTION,    "YResolution");
  243.     CmpLongField(TIFFTAG_GROUP3OPTIONS,    "Group3Options");
  244.     CmpLongField(TIFFTAG_GROUP4OPTIONS,    "Group4Options");
  245.     CmpShortField(TIFFTAG_RESOLUTIONUNIT,    "ResolutionUnit");
  246.     CmpShortField(TIFFTAG_PLANARCONFIG,    "PlanarConfiguration");
  247.     CmpLongField(TIFFTAG_ROWSPERSTRIP,    "RowsPerStrip");
  248.     CmpFloatField(TIFFTAG_XPOSITION,    "XPosition");
  249.     CmpFloatField(TIFFTAG_YPOSITION,    "YPosition");
  250.     CmpShortField(TIFFTAG_GRAYRESPONSEUNIT, "GrayResponseUnit");
  251.     CmpShortField(TIFFTAG_COLORRESPONSEUNIT, "ColorResponseUnit");
  252. #ifdef notdef
  253.     { u_short *graycurve;
  254.       CmpField(TIFFTAG_GRAYRESPONSECURVE, graycurve);
  255.     }
  256.     { u_short *red, *green, *blue;
  257.       CmpField3(TIFFTAG_COLORRESPONSECURVE, red, green, blue);
  258.     }
  259.     { u_short *red, *green, *blue;
  260.       CmpField3(TIFFTAG_COLORMAP, red, green, blue);
  261.     }
  262. #endif
  263.     CmpShortField2(TIFFTAG_PAGENUMBER,    "PageNumber");
  264.     CmpStringField(TIFFTAG_ARTIST,        "Artist");
  265.     CmpStringField(TIFFTAG_IMAGEDESCRIPTION,"ImageDescription");
  266.     CmpStringField(TIFFTAG_MAKE,        "Make");
  267.     CmpStringField(TIFFTAG_MODEL,        "Model");
  268.     CmpStringField(TIFFTAG_SOFTWARE,    "Software");
  269.     CmpStringField(TIFFTAG_DATETIME,    "DateTime");
  270.     CmpStringField(TIFFTAG_HOSTCOMPUTER,    "HostComputer");
  271.     CmpStringField(TIFFTAG_PAGENAME,    "PageName");
  272.     CmpStringField(TIFFTAG_DOCUMENTNAME,    "DocumentName");
  273.     CmpShortField(TIFFTAG_MATTEING,        "Matteing");
  274.     return (1);
  275. }
  276.  
  277. static void
  278. ContigCompare(sample, row, p1, p2, size)
  279.     int sample;
  280.     u_long row;
  281.     u_char *p1, *p2;
  282.     int size;
  283. {
  284.     register u_long pix;
  285.     register int ppb = 8/bitspersample;
  286.  
  287.     if (bcmp(p1, p2, size) == 0)
  288.         return;
  289.     switch (bitspersample) {
  290.     case 1: case 2: case 4: case 8: {
  291.         register u_char *pix1 = p1, *pix2 = p2;
  292.  
  293.         for (pix = 0; pix < imagewidth; pix1++, pix2++, pix += ppb)
  294.             if (*pix1 != *pix2)
  295.                 PrintDiff(row, sample, pix,
  296.                     *pix1, *pix2);
  297.         break;
  298.     }
  299.     case 16: {
  300.         register u_short *pix1 = (u_short *)p1, *pix2 = (u_short *)p2;
  301.  
  302.         for (pix = 0; pix < imagewidth; pix1++, pix2++, pix++)
  303.             if (*pix1 != *pix2)
  304.                 PrintDiff(row, sample, pix,
  305.                     *pix1, *pix2);
  306.         break;
  307.     }
  308.     }
  309. }
  310.  
  311. static void
  312. PrintDiff(row, sample, pix, w1, w2)
  313.     u_long row, pix;
  314.     register int w1, w2;
  315. {
  316.     register int mask1, mask2, s, ppb, bps;
  317.  
  318.     if (sample < 0)
  319.         sample = 0;
  320.     bps = bitspersample;
  321.     switch (bps) {
  322.     case 1:
  323.     case 2:
  324.     case 4:
  325.         mask1 =  ~((-1)<<bps);
  326.         s = (8-bps);
  327.         mask2 = mask1<<s;
  328.         for (; mask2; mask2 >>= bps, s -= bps, pix++) {
  329.             if ((w1 & mask2) ^ (w2 & mask2)) {
  330.                 printf(
  331.             "Scanline %lu, pixel %lu, sample %d: %01x %01x\n",
  332.                         row, pix, sample, (w1 >> s) & mask1,
  333.                     (w2 >> s) & mask1 );
  334.                 if (stoponfirstdiff)
  335.                     exit(1);
  336.             }
  337.         }
  338.         break;
  339.     case 8: 
  340.         printf("Scanline %lu, pixel %lu, sample %d: %02x %02x\n",
  341.             row, pix, sample, w1, w2);
  342.         if (stoponfirstdiff)
  343.             exit(1);
  344.         break;
  345.     case 16:
  346.         printf("Scanline %lu, pixel %lu, sample %d: %04x %04x\n",
  347.             row, pix, sample, w1, w2);
  348.         if (stoponfirstdiff)
  349.             exit(1);
  350.         break;
  351.     }
  352. }
  353.  
  354. static void
  355. SeparateCompare(reversed, sample, row, cp1, p2)
  356.     int reversed, sample;
  357.     u_long row;
  358.     register u_char *cp1, *p2;
  359. {
  360.     u_long npixels = imagewidth;
  361.     register int pixel;
  362.  
  363.     cp1 += sample;
  364.     for (pixel = 0; npixels-- > 0; pixel++, cp1 += samplesperpixel, p2++)
  365.         if (*cp1 != *p2) {
  366.             printf("Scanline %lu, pixel %lu, sample %d: ",
  367.                 row, pixel, sample);
  368.             if (reversed)
  369.                 printf("%02x %02x\n", *p2, *cp1);
  370.             else
  371.                 printf("%02x %02x\n", *cp1, *p2);
  372.             if (stoponfirstdiff)
  373.                 exit(1);
  374.         }
  375. }
  376.  
  377. static int
  378. checkTag(tif1, tif2, tag, name, p1, p2)
  379.     TIFF *tif1, *tif2;
  380.     char *name;
  381.     char *p1, *p2;        /* XXX should be void * */
  382. {
  383.  
  384.     if (TIFFGetField(tif1, tag, p1)) {
  385.         if (!TIFFGetField(tif2, tag, p2)) {
  386.             printf("%s tag appears only in %s\n",
  387.                 name, TIFFFileName(tif1));
  388.             return (0);
  389.         }
  390.         return (1);
  391.     } else if (TIFFGetField(tif2, tag, p2)) {
  392.         printf("%s tag appears only in %s\n", name, TIFFFileName(tif2));
  393.         return (0);
  394.     }
  395.     return (-1);
  396. }
  397.  
  398. #define    CHECK(cmp, fmt)                    \
  399.     switch (checkTag(tif1,tif2,tag,name,&v1,&v2)) {    \
  400.     case 1:    if (cmp)                \
  401.     case -1:    return (1);            \
  402.         printf(fmt, name, v1, v2);        \
  403.     case 0:    return (0);                \
  404.     }
  405.  
  406. static int
  407. CheckShortTag(tif1, tif2, tag, name)
  408.     TIFF *tif1, *tif2;
  409.     int tag;
  410.     char *name;
  411. {
  412.     u_short v1, v2;
  413.     CHECK(v1 == v2, "%s: %u %u\n");
  414. }
  415.  
  416. static int
  417. CheckShort2Tag(tif1, tif2, tag, name)
  418.     TIFF *tif1, *tif2;
  419.     int tag;
  420.     char *name;
  421. {
  422.     u_short v11, v12, v21, v22;
  423.  
  424.     if (TIFFGetField(tif1, tag, &v11, &v12)) {
  425.         if (!TIFFGetField(tif2, tag, &v21, &v22)) {
  426.             printf("%s tag appears only in %s\n",
  427.                 name, TIFFFileName(tif1));
  428.             return (0);
  429.         }
  430.         if (v11 == v21 && v12 == v22)
  431.             return (1);
  432.         printf("%s: <%u,%u> <%u,%u>\n", name, v11, v12, v21, v22);
  433.     } else if (TIFFGetField(tif2, tag, &v21, &v22))
  434.         printf("%s tag appears only in %s\n", name, TIFFFileName(tif2));
  435.     else
  436.         return (1);
  437.     return (0);
  438. }
  439.  
  440. static int
  441. CheckLongTag(tif1, tif2, tag, name)
  442.     TIFF *tif1, *tif2;
  443.     int tag;
  444.     char *name;
  445. {
  446.     u_long v1, v2;
  447.     CHECK(v1 == v2, "%s: %lu %lu\n");
  448. }
  449.  
  450. static int
  451. CheckFloatTag(tif1, tif2, tag, name)
  452.     TIFF *tif1, *tif2;
  453.     int tag;
  454.     char *name;
  455. {
  456.     float v1, v2;
  457.     CHECK(v1 == v2, "%s: %g %g\n");
  458. }
  459.  
  460. static int
  461. CheckStringTag(tif1, tif2, tag, name)
  462.     TIFF *tif1, *tif2;
  463.     int tag;
  464.     char *name;
  465. {
  466.     char *v1, *v2;
  467.     CHECK(strcmp(v1, v2) == 0, "%s: \"%s\" \"%s\"\n");
  468. }
  469.  
  470. static void
  471. eof(name, row, s)
  472.     char *name;
  473.     u_long row;
  474.     int s;
  475. {
  476.  
  477.     printf("%s: EOF at scanline %lu", name, row);
  478.     if (s >= 0)
  479.         printf(", sample %d", s);
  480.     printf("\n");
  481. }
  482.